package org.compiere.process;

import java.math.BigDecimal;
import java.math.MathContext;
import java.sql.Timestamp;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.MBPartner;
import org.compiere.model.Mhrmlimitholiday;
import org.compiere.model.Mhrmpayment;
import org.compiere.model.Mhrmpaymentlist;
import org.compiere.model.Mhrmreserve;
import org.compiere.model.Mhrmreviewline;
import org.compiere.model.Mhrmsalaryemployee;
import org.compiere.model.X_hrm_salaryemployee;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.eevolution.model.X_HR_Employee;
import org.joda.time.DateTime;

import extend.org.compiere.hrm.AverageSalary;
import extend.org.compiere.hrm.Reserve;
import extend.org.compiere.hrm.TaxCompute;
import extend.org.compiere.hrm.TaxVariable;
import extend.org.compiere.hrm.TypePayment;


public class GenerateAmountSalary extends SvrProcess {

	private Timestamp dateFrom;
	private Timestamp edt;
	private int C_BPartner_ID = 0;
	private int HR_Block_ID  = 0;
	private int HR_Department_ID  = 0;
	private double SUM = .0;
	double HOLIDAYS = 2.5;   // 2.5 days set default, in future must be take configuration table
	/** The target date */
	private org.joda.time.DateTime targetDate = new org.joda.time.DateTime("2012-10-01");
	
	private double SUMTotal = .0;
	private double IPNTotal = .0;
	private double OPVTotal = .0;
	private double COTCHTotal = .0;
	private double CNALOGTotal = .0;
	
	/**	Employee List	*/
	private MBPartner[] m_lines;
	
	private Mhrmpayment payment = null; 
	private TaxVariable taxcomp = null;
	private AverageSalary average = null;
	private Mhrmlimitholiday holiDaylimit = null; 
	
	/** */
	String closeTax = "N";
			
	@Override
	protected void prepare() {
		
		ProcessInfoParameter[] para = getParameter();
		for (int i = 0; i < para.length; i++)
		{
			String name = para[i].getParameterName();
			if (name.equals("CloseTax"))
				closeTax = para[i].getParameter().toString();
			else
				log.log(Level.INFO, "Unknown Parameter: " + name);			
		}	
		
		payment = new Mhrmpayment(getCtx(), getRecord_ID(), null);
		
		if(payment.getDateFrom().getTime() < targetDate.getMillis())
			throw new AdempiereException(Msg.translate(Env.getCtx(), "PeriodNotValid"));
	}

	@Override
	protected String doIt() throws Exception {
		// 
		if (payment.getReversal_ID() > 0) {
			return Msg.translate(Env.getCtx(), "Terminated");
		}
		
		HR_Block_ID = payment.getHR_Block_ID();
		HR_Department_ID = payment.getHR_Department_ID();
		C_BPartner_ID = payment.getC_BPartner_ID();
		// Get last day of month
		dateFrom = payment.getDateFrom();
		DateTime dt = new DateTime(dateFrom.getTime());
		DateTime lastDayOfMonth = dt.dayOfMonth().withMaximumValue();
		edt = new Timestamp(lastDayOfMonth.getMillis());
		 //
		 MBPartner bp = new MBPartner(getCtx(), 0, null);
	     X_HR_Employee he = null;
	     m_lines = bp.getPartnerEmployeeDate(C_BPartner_ID, HR_Block_ID, HR_Department_ID, dateFrom, true);
		 //m_lines = bp.getPartnerEmployee(C_BPartner_ID, HR_Block_ID, HR_Department_ID);			 
		 //
		 for(MBPartner b: m_lines){
			// Title
		    he = X_HR_Employee.getHR_Employee(b.getC_BPartner_ID(), null);
		    Mhrmsalaryemployee mhrmsle = Mhrmsalaryemployee.getSalary(b.getC_BPartner_ID(), dateFrom);
		    if (mhrmsle != null){
		    	//throw new AdempiereException (" Salary settings for person - " + b.getName() + " not set.");
		    BigDecimal salary = Mhrmsalaryemployee.getAmount(b.getC_BPartner_ID(), edt);
		    if (salary == null){ 
		       	throw new AdempiereException (" Amount or timesheet for person is empty - " + b.getName());
		    }
			    BigDecimal amount = Mhrmsalaryemployee.getFullSalary(b.getC_BPartner_ID(), dateFrom);
			    int salaryday = Mhrmsalaryemployee.getSalaryDays(b.getC_BPartner_ID(), dateFrom);
			    
				    Mhrmpaymentlist payList = Mhrmpaymentlist.getPaymentListRec(b.getC_BPartner_ID(), dateFrom);
				    if (payList == null || payList.get_ID() == 0){
				    		payList = new Mhrmpaymentlist(getCtx(), 0, get_TrxName());
				    }
				    payList.sethrm_payment_ID(getRecord_ID());
				    payList.setC_BPartner_ID(b.getC_BPartner_ID());
				    payList.setHR_Department_ID(he.getHR_Department_ID());
				    payList.setHR_Job_ID(he.getHR_Job_ID());
				    payList.setDateFrom(dateFrom);
				    payList.sethrm_amountsalary(salary);
				    payList.sethrm_days(salaryday);
				    
				    if (X_hrm_salaryemployee.HRM_SALARYTYPE_Direct.equals(mhrmsle.gethrm_salarytype())){
				    	payList.sethrm_salarytype(X_hrm_salaryemployee.HRM_SALARYTYPE_Direct);
				    }else{
				    	payList.sethrm_salarytype(X_hrm_salaryemployee.HRM_SALARYTYPE_Inverse);
				    }
				  
				    SUM = amount.doubleValue();				   	    	    
				 
				    /** Generate employee tax */
					taxcomp =  TaxCompute.GetTax(b.getC_BPartner_ID(), SUM, dateFrom, TypePayment.PAYMENT);
				    //
				    payList.sethrm_IPN(new BigDecimal(taxcomp.getIPN())); 		IPNTotal += taxcomp.getIPN(); 
				    payList.sethrm_OPV(new BigDecimal(taxcomp.getOPV())); 		OPVTotal += taxcomp.getOPV();
				    payList.sethrm_total(new BigDecimal(taxcomp.getTOTAL()));	SUMTotal += taxcomp.getTOTAL(); 
				    // Set social tax variables
				    payList.sethrm_COtch(new BigDecimal(taxcomp.getCOTCH()));	COTCHTotal += taxcomp.getCOTCH();
				    payList.sethrm_CNalog(new BigDecimal(taxcomp.getCNALOG()));	CNALOGTotal += taxcomp.getCNALOG();
				    if (closeTax.equals("Y"))
				    	payList.setProcessed(true);
				    payList.saveEx();
				   
				    /*				 
				    amount = null;		    
				    // Generate limit holidays reserve sum
				    
				    
				    String sql = " select coalesce(amount,0) from adempiere.hrm_salarysum_v where hrm_payment_list_id = " + payList.gethrm_payment_list_ID();
					
					PreparedStatement pstmt = null;
					ResultSet rs = null;
					pstmt = null;
					rs = null;
					
					BigDecimal amout = new BigDecimal(0);
						
					try{
						pstmt = DB.prepareStatement(sql, get_TrxName());
						rs = pstmt.executeQuery();
						while (rs.next()) {
							amout = rs.getBigDecimal(1);
						}
					}catch(SQLException e){
						log.log(Level.WARNING, e.getLocalizedMessage());
					}
					finally
					{
						DB.close(rs, pstmt);
						rs = null; pstmt = null;
					}
				    
//				    double reserve = amout.doubleValue();
				    double reserve = 0;
				    
//				    reserve = reserve * 9.09 / 100;//salary.divide(new BigDecimal(22)).multiply(new BigDecimal(2))
//				    
				    double range = 0;// reserve / 2;
//				    
//				    double tax1 = reserve * 5.40 / 100;
//				    double tax2 = reserve * 4.50 / 100;				     
//				    
//					reserve += tax1 + tax2;
					
//					Timestamp BeginMonth = format.format(s1);
					
				    Timestamp t = null;
				    Timestamp t2 = null;
				    
			    	try{
			    		SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
			    		String s1 = "01." + (payList.getDateFrom().getMonth()+1) + "." + (payList.getDateFrom().getYear() + 1900);
			        	Date d = format.parse(s1);
			        	
			        	Calendar c = Calendar.getInstance();
			        	c.setTime(d);
			        	c.add(Calendar.MONTH, 1);
			        	d = c.getTime();
			        	
			        	Date d2 = payList.getDateFrom();
			        	c.setTime(d2);
			        	c.add(Calendar.MONTH, 1);
			        	d2 = c.getTime();
			        	
			    		t = new Timestamp(d.getTime());
			    		t2 = new Timestamp(d2.getTime());
			        	    		
			    	}catch(Exception e){}
					
					    sql = " select coalesce(sum(fa.amtacctcr),0) " +
					    				" from adempiere.fact_acct fa " +
					    				" inner join adempiere.c_elementvalue e on c_elementvalue_id = fa.account_id " +
					    				" where fa.c_bpartner_id = " + payList.getC_BPartner_ID() +
					    				" and fa.account_id = 1005507 " + 
					    				" and fa.dateacct between '" + t + "' and '" + t2 +"'";
						
						pstmt = null;
						rs = null;
						boolean calculatedThisMonth = false; 
						amout = new BigDecimal(0);
							
						try{
							pstmt = DB.prepareStatement(sql, get_TrxName());
							rs = pstmt.executeQuery();
							while (rs.next()) {
								if(rs.getBigDecimal(1).doubleValue() > 0)
									calculatedThisMonth = true;
								
							}
						}catch(SQLException e){
							log.log(Level.WARNING, e.getLocalizedMessage());
						}
						finally
						{
							DB.close(rs, pstmt);
							rs = null; pstmt = null;
						}
						
						if(!calculatedThisMonth){
						    sql = " select coalesce(sum(fa.amtacctcr),0) " +
				    				" from adempiere.fact_acct fa " +
				    				" inner join adempiere.c_elementvalue e on c_elementvalue_id = fa.account_id " +
				    				" where fa.c_bpartner_id = " + payList.getC_BPartner_ID() +
				    				" and fa.account_id = 1005507 "; 
					
							pstmt = null;
							rs = null;
							
							try{
								pstmt = DB.prepareStatement(sql, get_TrxName());
								rs = pstmt.executeQuery();
								while (rs.next()) {
									reserve = rs.getBigDecimal(1).doubleValue();
//									reserve += rs.getBigDecimal(1).doubleValue();
								}
							}catch(SQLException e){
								log.log(Level.WARNING, e.getLocalizedMessage());
							}
							finally
							{
								DB.close(rs, pstmt);
								rs = null; pstmt = null;
							}
						}
*/						
				    int account_id = 1005507; // reserve account id
					Reserve reserve = new Reserve(payList.getC_BPartner_ID(),dateFrom,Mhrmreserve.RESERVE_VACATION, account_id);
				    
				    

				    holiDaylimit = Mhrmlimitholiday.getLimitHoliday(b.getC_BPartner_ID(),null);
				    if (holiDaylimit == null)
				    	throw new AdempiereException (" Limit holidays for person is empty " + b.getC_BPartner_ID());
				    if (holiDaylimit.getC_BPartner_ID() == 0)
				    	throw new AdempiereException (" Limit holidays this person: " + b.getC_BPartner_ID() + " not set");
		
//				    if(calculatedThisMonth){
					    //holiDaylimit.sethrm_salaryrange_ID(new BigDecimal(range).setScale(2, BigDecimal.ROUND_HALF_UP));
					    holiDaylimit.sethrm_holidayreserve(reserve.getSectional(Mhrmreserve.RESERVE_SECTIONAL_CHARGE).setScale(2, BigDecimal.ROUND_HALF_UP));
//		 			}
				    holiDaylimit.saveEx();				    
		    }    	
		 }
		 
		 if (payment.getC_BPartner_ID() == 0
				 && payment.getHR_Department_ID() == 0
				 && payment.getHR_Block_ID() == 0 ){
			 
			 Mhrmreviewline[] revlist = Mhrmreviewline.getRevLineArray(edt); 
			 for(Mhrmreviewline r:revlist){
				 he = X_HR_Employee.getHR_Employee(r.getC_BPartner_ID(), false);
				 Mhrmsalaryemployee mhrmsle = Mhrmsalaryemployee.getSalary(r.getC_BPartner_ID(), dateFrom);
				    
				    	//throw new AdempiereException (" Salary settings for person - " + b.getName() + " not set.");
				    BigDecimal salary = Mhrmsalaryemployee.getAmount(r.getC_BPartner_ID(), edt);
				    if (salary == null){ 
				       	throw new AdempiereException (" Amount or timesheet for person is empty - ");
				    }
					BigDecimal amount = Mhrmsalaryemployee.getFullSalary(r.getC_BPartner_ID(), dateFrom);
					int salaryday = Mhrmsalaryemployee.getSalaryDays(r.getC_BPartner_ID(), dateFrom);
					    
				 Mhrmpaymentlist payList = Mhrmpaymentlist.getPaymentListRec(r.getC_BPartner_ID(), dateFrom);
				    if (payList == null || payList.get_ID() == 0){
				    		payList = new Mhrmpaymentlist(getCtx(), 0, get_TrxName());
				    }
				    payList.sethrm_payment_ID(getRecord_ID());
				    payList.setC_BPartner_ID(r.getC_BPartner_ID());
				    payList.setHR_Department_ID(he.getHR_Department_ID());
				    payList.setHR_Job_ID(he.getHR_Job_ID());
				    payList.setDateFrom(dateFrom);			    
				    
				    if (mhrmsle != null){

				    	payList.sethrm_amountsalary(salary);
					    payList.sethrm_days(salaryday);
					    
					    if (X_hrm_salaryemployee.HRM_SALARYTYPE_Direct.equals(mhrmsle.gethrm_salarytype())){
					    	payList.sethrm_salarytype(X_hrm_salaryemployee.HRM_SALARYTYPE_Direct);
					    }else{
					    	payList.sethrm_salarytype(X_hrm_salaryemployee.HRM_SALARYTYPE_Inverse);
					    }
					  
					    SUM = amount.doubleValue();				   	    	    
					 
					    /** Generate employee tax */
						taxcomp =  TaxCompute.GetTax(r.getC_BPartner_ID(), SUM, dateFrom, TypePayment.PAYMENT);
					    //
					    payList.sethrm_IPN(new BigDecimal(taxcomp.getIPN())); 		IPNTotal += taxcomp.getIPN(); 
					    payList.sethrm_OPV(new BigDecimal(taxcomp.getOPV())); 		OPVTotal += taxcomp.getOPV();
					    payList.sethrm_total(new BigDecimal(taxcomp.getTOTAL()));	SUMTotal += taxcomp.getTOTAL(); 
					    // Set social tax variables
					    payList.sethrm_COtch(new BigDecimal(taxcomp.getCOTCH()));	COTCHTotal += taxcomp.getCOTCH();
					    payList.sethrm_CNalog(new BigDecimal(taxcomp.getCNALOG()));	CNALOGTotal += taxcomp.getCNALOG();
				    }else{
					    payList.sethrm_IPN(new BigDecimal(0)); 		 
					    payList.sethrm_OPV(new BigDecimal(0));
					    payList.sethrm_total(new BigDecimal(0)); 
					    // Set social tax variables
					    payList.sethrm_COtch(new BigDecimal(0));
					    payList.sethrm_CNalog(new BigDecimal(0));
				    }
				    if (closeTax.equals("Y"))
				    	payList.setProcessed(true);
				    payList.saveEx();
				    
			 }
		 }
		
		 
		 MathContext mc = new MathContext(2);
		 payment.sethrm_amountsalary(new BigDecimal(SUMTotal).round(mc));
		 payment.sethrm_IPN(new BigDecimal(IPNTotal).round(mc));
		 payment.sethrm_OPV(new BigDecimal(OPVTotal).round(mc));
		 payment.sethrm_COtch(new BigDecimal(COTCHTotal).round(mc));
		 payment.sethrm_CNalog(new BigDecimal(CNALOGTotal).round(mc));
		 if (payment.equals("Y")){
			 payment.setProcessed(true);
		}
		 payment.saveEx();
//		 payment.setProcessed(false);
		 
		 return Msg.translate(Env.getCtx(), "Success");
	}
	
	protected void getSalaryTotal(){
		
	}	
}
